package com.ming.flowlayout_lib;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

import java.util.HashSet;
import java.util.Set;

public class FlowLayout extends TagFlowLayout implements View.OnClickListener {
    //单选
    public static final int SINGLECHOICE = 1;
    //多选
    public static final int MULTIPLECHOICE = 0;
    //可选中item数量
    private int maxSelectedCount = SINGLECHOICE;
    //item点击监听
    private OnItemClickLienter onItemClickLienter;
    //item选择监听
    private OnItemSelectedChangeLisenter onItemSelectedChangeLisenter;

    //item选中集合
    Set<View> selectedItemSet = new HashSet<>();

    //布局方向常量
    public static final int LEFT = 0;
    public static final int CENTER = 1;
    public static final int RIGHT = 2;

    public static final int ITEM_TOP = 3;
    public static final int ITEM_CENTER = 4;
    public static final int ITEM_BOTTOM = 5;

    //是否激活选择功能
    private boolean selectedEnable = true;


    public FlowLayout(Context context) {
        this(context, null);
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //初始清空集合
        selectedItemSet.clear();

        //获取自定义属性
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout);

        //获取最大可选择的数量，默认单选
        maxSelectedCount = typedArray.getInt(R.styleable.FlowLayout_max_select, SINGLECHOICE);
        //获取是否激活选中功能
        selectedEnable = typedArray.getBoolean(R.styleable.FlowLayout_isCheckedEnable, true);
        //获取item的布局位置  top | center | bottom
        setItemGravity(typedArray.getInt(R.styleable.FlowLayout_item_vertical_gravity, 3));
        //设置布局方向
        setGravity(typedArray.getInt(R.styleable.FlowLayout_flow_gravity, 0));

        //回收属性集合
        typedArray.recycle();

        dataViewChange();
    }


    @Override
    public void onClick(View v) {
        int vindex = ((ViewGroup) v.getParent()).indexOfChild(v);
        //判断点击监听是否存在
        if (onItemClickLienter != null)
            onItemClickLienter.onClick(vindex, v, FlowLayout.this);
        //处理选中的item点击事件
        if (selectedEnable) {
            if (selectedItemSet.contains(v)) {
                //选中状态，设置为未选中状态
                setChildUnSelected(vindex, v);
            } else {
                //未选中状态，设置成选中状态
                setChildSelected(vindex, v);
            }
        }
    }

    /**
     * 将view加入flowlayout
     */
    private void dataViewChange() {
        for (int i = 0; i < getChildCount(); i++) {
            //输入的view
            final View view = getChildAt(i);
            //为itemview设置点击监听
            view.setOnClickListener(this);
        }
    }


    /**
     * 选中item
     *
     * @param itemView 选中的view
     * @param postion  itemview在集合中的下标
     */
    private void setChildSelected(int postion, View itemView) throws FlowSelectedException{
        if (selectedEnable && itemView != null) {
            if (maxSelectedCount == SINGLECHOICE && selectedItemSet.iterator().hasNext()) {
                //单选
                //取消选择
                View un_view = selectedItemSet.iterator().next();
                int vindex = ((ViewGroup) un_view.getParent()).indexOfChild(un_view);
                setChildUnSelected(vindex, un_view);
            } else if (maxSelectedCount != MULTIPLECHOICE && selectedItemSet.size() == maxSelectedCount) {
                //多选--规定数量
                //选中数量到达设置数量，不进行操作了
                setChildFullSelected();
                return;
            }
            //将选中的item的下标添加到集合中

            selectedItemSet.add(itemView);
            if (onItemSelectedChangeLisenter != null) {
                onItemSelectedChangeLisenter.onSelected(postion, itemView);
            }else {
                FlowSelectedException exception = new FlowSelectedException("OnItemSelectedChangeLisenter是必须的");
                throw exception;
            }
        }
    }

    /**
     * 取消选中item
     *
     * @param itemView 选中的view
     * @param postion  itemview在集合中的下标
     */
    private void setChildUnSelected(int postion, View itemView) throws FlowSelectedException{
        //将选中的item的下标在集合中移除
        selectedItemSet.remove(itemView);
        if (onItemSelectedChangeLisenter != null) {
            onItemSelectedChangeLisenter.onUnSelected(postion, getChildAt(postion));
        }else {
            FlowSelectedException exception = new FlowSelectedException("OnItemSelectedChangeLisenter是必须的");
            throw exception;
        }
    }

    /**
     * 选中item数量限制
     */
    private void setChildFullSelected()  throws FlowSelectedException{
        if (onItemSelectedChangeLisenter != null){
            onItemSelectedChangeLisenter.onFullSelected(selectedItemSet);
        }else {
            FlowSelectedException exception = new FlowSelectedException("OnItemSelectedChangeLisenter是必须的");
            throw exception;
        }
    }


    //----------------------------------------监听器-----------------------------------------

    /**
     * item点击监听
     */
    public interface OnItemClickLienter {
        void onClick(int position, View itemView, FlowLayout flowLayout);
    }

    /**
     * item选择监听
     */
    public interface OnItemSelectedChangeLisenter {

        void onSelected(int position, View itemView);

        void onUnSelected(int position, View itemView);

        void onFullSelected(Set<View> viewSet);
    }

    /*--------------------------------------------------对外方法-----------------------------------------------------*/
    //-----------------------------初始化方法---------------------------------------

    @Override
    public void addView(View child, int index, LayoutParams params) {
        super.addView(child, index, params);
        child.setOnClickListener(this);
    }

    /**
     * 设置布局方向
     *
     * @param mGravity 布局方向 LEFT CENTER RIGHT
     * @return
     */
    @Override
    public FlowLayout setGravity(int mGravity) {
        return (FlowLayout) super.setGravity(mGravity);
    }

    /**
     * 设置item的布局位置  ITEM_TOP | ITEM_CENTER | ITEM_BOTTOM
     *
     * @return
     */
    @Override
    public FlowLayout setItemGravity(int itemGravity) {
        return (FlowLayout) super.setItemGravity(itemGravity);
    }

    /**
     * 是否激活选择功能
     *
     * @param selectedEnable
     */
    public FlowLayout setSelectedEnable(boolean selectedEnable) {
        this.selectedEnable = selectedEnable;
        return this;
    }


    /**
     * 设置选择状态
     * --多选|单选|限制数量
     *
     * @param maxSelectedCount 最大选中数量
     * @return
     */
    public FlowLayout setMaxSelectedCount(int maxSelectedCount) {
        selectedEnable = true;
        this.maxSelectedCount = maxSelectedCount;
        return this;
    }

    /**
     * 设置item选中
     *
     * @param positions
     */
    public void setItemSelected(int... positions) {
        if (selectedEnable) {
            for (int p : positions) {
                setChildSelected(p, getChildAt(p));
            }
        }
    }

    /**
     * 设置item取消选中
     *
     * @param positions
     */
    public void setItemUnSelected(int... positions) {
        if (selectedEnable) {
            for (int p : positions) {
                setChildUnSelected(p, getChildAt(p));
            }
        }

    }

    /**
     * 设置item点击监听
     *
     * @param onItemClickLienter
     * @return
     */
    public FlowLayout setOnItemClickLienter(OnItemClickLienter onItemClickLienter) {
        this.onItemClickLienter = onItemClickLienter;
        return this;
    }

    /**
     * item选择监听
     *
     * @param onItemSelectedChangeLisenter
     * @return
     */
    public FlowLayout setOnItemSelectedChangeLisenter(OnItemSelectedChangeLisenter onItemSelectedChangeLisenter) {
        this.onItemSelectedChangeLisenter = onItemSelectedChangeLisenter;
        return this;
    }


//--------------------------------------操作方法------------------------------------------------------

    /**
     * 获取item选择集合
     *
     * @return
     */
    public Set<View> getSelectedSet() {
        return selectedItemSet;
    }
}
